package per.ethan.javase.designparttern.singleton;

import java.lang.reflect.Constructor;

/**
 * @author Ethan
 * @date 2020/06/01 15:15
 * 懒汉模式
 */
public class LazySingleton {

    private static volatile LazySingleton singleton;

    private LazySingleton() {

    }

    /**
     * 双重检查锁，防止多线程问题
     * 不是原子性操作，其底层如下：
     * 1、分配内存空间
     * 2、执行构造方法，初始化对象
     * 3、将该对象指向分配的内存空间
     * 上述过程如果发生在多线程中，会有指令重排问题
     * 在多线程情况下，A线程正常，B线程可能就会有判断对象不为空直接返回的情况
     *
     * @return
     */
    public static LazySingleton getInstance() {
        if (null == singleton) {
            synchronized (LazySingleton.class) {
                if (null == singleton) {
                    singleton = new LazySingleton();
                }
            }
        }
        return singleton;
    }

    public static void main(String[] args) {
        /*for (int i = 0; i < 5000; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + LazySingleton.getInstance());
            }).start();
        }*/
        LazySingleton instance = LazySingleton.getInstance();
        try {
            Constructor<LazySingleton> constructor = LazySingleton.class.getDeclaredConstructor();
            constructor.setAccessible(true);
            LazySingleton instance2 = constructor.newInstance();
            System.out.println(instance == instance2);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}
